package org.mokusakura.web.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import org.mokusakura.domain.AlipayConfig;
import org.mokusakura.domain.Order;
import org.mokusakura.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Controller
public class PayController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private AlipayConfig alipayConfig;
    @Autowired
    private AlipayClient client;

    // 将request中的参数转换成Map
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        return params;
    }

    @GetMapping("/pay/{orderId}")
    public void requestToPay(@PathVariable Long orderId, HttpServletResponse response) throws IOException {

        Order order = orderService.getOrderByOrderId(orderId);
        if (order != null) {
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//创建API对应的request
            alipayRequest.setReturnUrl(alipayConfig.getReturnUrl() + order.getOrderId());
            alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl());//在公共参数中设置回跳和通知地址
            AlipayTradePagePayModel model = new AlipayTradePagePayModel();
            model.setOutTradeNo(order.getOrderId().toString());
            model.setProductCode("FAST_INSTANT_TRADE_PAY");
            model.setSubject("JpetStore Order");
            model.setTotalAmount(order.getTotalPrice().toString());
            System.out.println(client);
            alipayRequest.setBizModel(model);
            String form = "";
            try {
                form = client.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
            response.setContentType("text/html;charset=" + alipayConfig.getCharset());
            response.getWriter().write(form);//直接将完整的表单html输出到页面
            response.getWriter().flush();
            response.getWriter().close();
        }
    }

    @RequestMapping("/ali_callback")
    @ResponseBody
    public String callback(HttpServletRequest request) {
        Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        try {
            // 调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(),
                                                              alipayConfig.getCharset(), alipayConfig.getSignType());
            if (signVerified) {

                //交易状态
                String tradeStatus = new String(request.getParameter("trade_status").getBytes(
                        StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);

                // 支付成功
                if ("TRADE_SUCCESS".equals(tradeStatus)
                        || "TRADE_FINISHED".equals(tradeStatus)) {

                    Order order = orderService.getOrderByOrderId(Long.valueOf(params.get("out_trade_no")));
                    order.setStatus((byte) 1);
                    orderService.updateOrder(order);
                    return "success";

                } else {
                    return "failure";
                }
            } else {
                return "failure";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "failure";
        }
    }


    /**
     * TODO 实现这个
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
     * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
     * 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
     *
     * @param params-阿里传来的参数
     */
    private void check(Map<String, String> params) {
//        String outTradeNo = params.get("out_trade_no");
//
//        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
//        Order order = orderService.getOrderByOrderId(outTradeNo); // 这个方法自己实现
//        if (order == null) {
//            throw new AlipayApiException("out_trade_no错误");
//        }
//
//        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
//        long total_amount = new BigDecimal(params.get("total_amount")).multiply(new BigDecimal(100)).longValue();
//        if (total_amount != order.getPayPrice().longValue()) {
//            throw new AlipayApiException("error total_amount");
//        }
//
//        // 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
//        // 第三步可根据实际情况省略
//
//        // 4、验证app_id是否为该商户本身。
//        if (!params.get("app_id").equals(alipayConfig.getAppid())) {
//            throw new AlipayApiException("app_id不一致");
//        }
    }

}

